package h5

import (
	"chess_platform/controllers"
	. "chess_platform/internal/common"
	"chess_platform/internal/login"
	"chess_platform/models/client"
	"chess_platform/models/h5"
	"fmt"
	"time"
)

//[h5]公共对外的接口模块,不需要token, 现做了用微信登录限制攻击
type PublicController struct {
	BaseController
}

func (b *PublicController) URLMapping() {
	b.Mapping("WeChatOpenId", b.WeChatOpenId)
	//店铺
	b.Mapping("Shop", b.Shop)
	b.Mapping("FindPlayer", b.FindPlayer)
	b.Mapping("ListPlayerCardRecord", b.ListPlayerCardRecord)
	b.Mapping("ListAutoCard", b.ListAutoCard)
	//给玩家直充
	b.Mapping("IPayCreateOrder", b.IPayCreateOrder)
	b.Mapping("QueryOrder", b.QueryOrder)

}

type OpenId struct {
	OpenId string `json:"open_id"`
}

func (b *PublicController) Prepare() {
	LogH5.Debug("用户输入:" + string(b.Ctx.Input.RequestBody))
	LogH5.Debug("用户访问url:" + b.Ctx.Input.URL())
	b.Res = new(controllers.Response)
	_, actionName := b.GetControllerAndAction()
	LogH5.Debug("用户访问action:" + actionName)
	if actionName == "WeChatOpenId" {
		return
	}
	//检查open_id
	var o OpenId
	err := b.Unmarshal(&o)
	if err != nil || o.OpenId == "" {
		b.ResponseFail("未带open_id访问")
		return
	}
	if !RedisCache.IsExist(o.OpenId) {
		b.ResponseFail("访问已过期,请重新登录")
		return
	}
	if !AccessLimit(o.OpenId, 600, 60) {
		b.ResponseFail("操作过于频繁，请稍候再操作")
		return
	}
}

// --------------------------------以下主要是代理店铺相关的接口-------------------------
// @Title 代理的店铺主页
// @Description 代理的店铺主页
// @Param   agent_id  body    int     true      "代理id"
// @Success 0 {string}
// @router /shop [post]
func (b *PublicController) Shop() {
	type Params struct {
		AgentId int64 `json:"agent_id" valid:"Required"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}
	if !b.ValidParams(&p) {
		return
	}
	var data *H5User
	key := fmt.Sprintf("%v%v", KeyAgentInfo, p.AgentId)
	err := GetCache(MemCache, key, data)
	if err != nil {
		field := []string{"uid", "nickname", "head_img_url"}
		data, err = h5.SpecifyUserInfoById(p.AgentId, field)
		if err != nil {
			LogH5.Error(b.DatabaseError(err.Error()))
			return
		}
		SetCache(MemCache, key, data, 300) //5分钟
	}
	if data == nil {
		b.Res.Code = ErrNotFound
		b.Res.Msg = "店铺不存在或已下架"
		b.Response()
		return
	}
	b.Res.Data = data
	b.ResponseSuccess()
}

// @Title 获取玩家信息
// @Description 获取玩家信息,代充前查找玩家id,以便确认
// @Param   uid  body    int     true      "玩家uid"
// @Success 0 {object} client.User
// @router /find-player [post]
func (b *PublicController) FindPlayer() {
	type Params struct {
		Uid int64 `json:"uid"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}
	b.Valid.Required(p.Uid, "uid").Message("请输入正确的玩家ID")
	dbUser, err := client.QueryUserInfoById(p.Uid)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	if dbUser.Uid == 0 {
		b.Res.Code = ErrNotFound
		b.Res.Msg = MsgErrUserNotFound
		b.Response()
		return
	}
	data := map[string]interface{}{
		"uid":      dbUser.Uid,
		"nickname": dbUser.Nickname,
		"imageurl": dbUser.ImageUrl,
	}
	b.Res.Data = data
	b.ResponseSuccess()
}

// @Title 获取玩家在此代理的充值记录
// @Description 获取玩家在此代理的充值记录
// @Param   page_size    body   int     true       "每页显示数量"
// @Param   page_index   body   int     true       "第几页"
// @Param   player_id    body    int     true      "玩家uid"
// @Param   agent_id     body    int     true      "代理uid"
// @Success 0 {object} client.User
// @router /list-player-card-record [post]
func (b *PublicController) ListPlayerCardRecord() {
	type Params struct {
		ListParams
		AgentId  int64 `json:"agent_id" valid:"Required"`
		PlayerId int64 `json:"player_id" valid:"Required"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}
	if !b.ValidParams(&p) {
		return
	}
	data, count, err := h5.ListPlayerCardRecord(p.ListParams, p.AgentId, p.PlayerId)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	b.Res.Count = count
	b.Res.Data = data
	b.ResponseSuccess()
}

// @Title 玩家直充时看到钻石列表
// @Description 玩家直充时看到钻石列表
// @Success 0 {object} []common.Card 玩家直充钻石列表
// @router /list-auto-card [post]
func (b *PublicController) ListAutoCard() {
	card, err := h5.ListCard(RulePlayerCardPrice)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	b.Res.Data = card
	b.ResponseSuccess()
}

//----------------------------以下是店铺支付方面的接口------------------------
// @Title 查询订单支付情况
// @Description 查询订单支付情况
// @Param   order_id         body    int true      "订单id"
// @Success 0 {string} 订单状态
// @Failure 400
// @Failure 404
// @router /query-order [post]
func (b *PublicController) QueryOrder() {
	type Params struct {
		OrderId int64 `json:"order_id" valid:"Required"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}
	if !b.ValidParams(&p) {
		return
	}
	order, err := h5.OrderById(p.OrderId)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	if order == nil {
		b.Res.Code = ErrNotFound
		b.Res.Msg = MsgErrOrderNoExist
		b.Response()
		return
	}
	b.Res.Data = order.Status
	b.ResponseSuccess()
}

// @Title 店铺里预支付(爱贝,玩家直充购买钻石)
// @Description 店铺里里预支付(爱贝,玩家直充购买钻石)
// @Param   id             body    int true      "购买钻石数量对应的id"
// @Param   uid            body    int true      "玩家id"
// @Param   agent_id       body    int true      "在哪个代理店铺里买的，对应的代理id"
// @Param   pay_type       body    int true      "支付类型,2-微信支付,3-支付宝支付"
// @Param   url_r          body    int true      "支付成功回调url"
// @Param   url_h          body    int true      "支付取消回调url"
// @Success 0 {string} 状态码
// @Failure 400
// @Failure 404
// @router /ipay-create-order [post]
func (b *PublicController) IPayCreateOrder() {
	type Params struct {
		Id      int64  `json:"id" valid:"Required"`
		Uid     int64  `json:"uid" valid:"Required"`
		AgentId int64  `json:"agent_id" valid:"Required"`
		PayType int64  `json:"pay_type" valid:"Range(2,3)"`
		UrlR    string `json:"url_r" valid:"Required"`
		UrlH    string `json:"url_h" valid:"Required"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}
	if !b.ValidParams(&p) {
		return
	}
	dbUser, err := client.QueryUserInfoById(p.Uid)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	if dbUser.Uid == 0 {
		b.Res.Code = ErrNotFound
		b.Res.Msg = fmt.Sprintf("您输入的玩家ID:%v不存在,请检查", p.Uid)
		b.Response()
		return
	}
	field := []string{"uid"}
	a, err := h5.SpecifyUserInfoById(p.AgentId, field)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	if a.Uid == 0 {
		b.Res.Code = ErrNotFound
		b.Res.Msg = fmt.Sprintf("您充值的店铺ID:%v不存在,请检查", p.AgentId)
		b.Response()
		return
	}

	//找出买多少张钻石，多少钱
	card, err := h5.CardById(p.Id, RulePlayerCardPrice)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	if card == nil {
		b.Res.Code = ErrNotFound
		b.Res.Msg = MsgErrCardNoExist
		b.Response()
		return
	}
	order := map[string]interface{}{
		"uid":        p.Uid,     //玩家id
		"agent_id":   p.AgentId, //店铺对应的代理id
		"user_type":  Player,
		"order_type": OrderDiamond,
		"pay_type":   p.PayType,
		"amount":     card.Amount,
		"card_num":   card.Num,     //赠送的钻石与购买的暂时没有区别
		"give_num":   card.GiveNum, //搞活动系统赠送的钻石
		"status":     OrderNotPay,
		"order_time": time.Now().Unix(),
	}
	orderId, err := h5.PreOrderPay(order)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}

	notifyUrl := BasePayCallBack + "/v1/h5/ipay-callback"
	orderIdStr := fmt.Sprintf("%v%v", H5IPayPre, orderId)
	price := float32(card.Amount) / 100 //我们数据库存在的整型,单位是分,所以要除以100转为元
	transId, err := H5IPay.CreateIpayOrder(1, "", orderIdStr, price, "xiashen", "", notifyUrl)
	if err != nil {
		LogH5.Error(b.SystemError(err.Error()))
		return
	}
	updateData := map[string]interface{}{
		"transaction_id": transId,
	}
	_, err = h5.UpdateOrder(updateData, orderId)
	if err != nil {
		LogH5.Error(fmt.Sprintf("写入爱贝的订单号失败:%v", err.Error()))
	}

	payUrl, err := H5IPay.GetHtml5PayUrl(transId, p.UrlR, p.UrlH, IPayPayType(p.PayType))
	if err != nil {
		LogH5.Error(b.SystemError(err.Error()))
		return
	}
	b.Res.Data = payUrl
	b.ResponseSuccess()
}

// @Title 获取微信open_id
// @Description 获取微信open_id
// @Param   code       body    string  true      "微信用户code"
// @Success 0 {string} token
// @Failure 400
// @Failure 404
// @router /weChat-openId [post]
func (b *PublicController) WeChatOpenId() {
	type Params struct {
		Code string `json:"code" valid:"Required"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}
	if !b.VerifyParamsError() {
		return
	}
	t, err := login.GetWeChatOpenIdAccessToken(p.Code)
	if err != nil {
		LogH5.Error(b.SystemError(err.Error()))
		return
	}
	if t.OpenId == "" {
		LogH5.Error(b.LoginRetry(fmt.Sprintf("无效的open_id:%v\n", t.OpenId)))
		return
	}
	b.Res.Data = t.OpenId
	RedisCache.Put(t.OpenId, 1, 3600*time.Second) //一个小时
	b.ResponseSuccess()
}
